fn outsider() {
    println!("outsider fn!");
}

pub mod lean_rust {

    mod top_level {
        pub fn hi_there() {
            println!("hi there");
        }

        pub mod low_level {
            pub fn hello_world() {
                println!("hello_world");
            }
        }
    }

    #[derive(Debug)]
    pub enum PersonId {
        // 括号里是和携带的数据的类型
        Passport(u32),
        UUID(String),
        IndentityCard(u32, u32, u32),
    }

    pub struct Person {
        pub name: String,
        last_name: String,
        age: u32,
        id: PersonId,
    }

    impl Person {
        // associated function
        // 这种方法适用于构造方法
        pub fn new() -> Person {
            Person {
                name: "default".to_string(),
                last_name: "default".to_string(),
                age: 0,
                id: PersonId::UUID("865fbd57-64b6-4064-8207-2368ead0436e".to_string()),
            }
        }

        pub fn from(name: String, last_name: String, age: u32, id: PersonId) -> Person {
            Person {
                name,
                last_name,
                age,
                id,
            }
        }

        pub fn name(&self) -> &String {
            &self.name
        }

        fn display(&self) {
            println!(
                "{} {} {} {:?}",
                self.name, self.last_name, self.age, self.id
            );
        }

        fn change_age(&mut self, new_age: u32) {
            self.age = new_age;
        }
    }
    /*
       感觉类似go的interface

       一组类型的通用接口。
       A trait就像数据类型可以实现的接口。
       当一个类型 实现一个特征，
       可以使用泛型将其抽象地视为该特征 或特质对象。
    */
    pub trait Log {
        fn display_info(&self);
        fn alert_something(&self) {
            println!("Default implementation~~~~~!")
        }
    }

    impl Log for Person {
        fn display_info(&self) {
            // absolute path
            // crate -> src/lib.rs and src/main.rs
            crate::lean_rust::top_level::hi_there();
            crate::lean_rust::top_level::low_level::hello_world();

            // relative path
            top_level::hi_there();
            top_level::low_level::hello_world();

            println!(
                "{} {} {} {:?}",
                self.name, self.last_name, self.age, self.id
            );
        }
    }

    pub struct Animal(pub String);

    impl Log for Animal {
        fn display_info(&self) {
            println!("{}", self.0);
        }

        fn alert_something(&self) {
            println!("Animal implementation~~~~~!")
        }
    }

    pub fn log_info(val: impl Log) {
        val.alert_something();
    }

    // 编译之后占空间更小,但是功能比较少
    pub fn log_info_2(val: &dyn Log) {
        val.alert_something();
    }
}
